<template>
  <el-drawer
    v-model="state.drawer.isShowDrawer"
    title="设置流程属性"
    :direction="direction"
    :before-close="handleClose"
    :show-close="false"
  >
    <component
      v-if="state.component"
      v-model="state.ruleForm"
      :is="getComponent(state.component)"
      :extendAttrConfig="props.extendAttrConfig || {}"
    >
      <template #[key]="data" v-for="(item, key) in $slots">
        <slot :name="key" v-bind="data || {}"></slot>
      </template>
    </component>
  </el-drawer>
</template>

<script setup lang="ts">
import {
  ref,
  defineExpose,
  computed,
  unref,
  reactive,
  watch,
  defineEmits,
  defineProps,
  inject,
} from "vue";
import { FlowFormModel, PropertyEvent } from "../types";
import start from "./start.vue";
import task from "./task.vue";
import transition from "./transition.vue";
import decision from "./decision.vue";
import fork from "./fork.vue";
import join from "./join.vue";
import custom from "./custom.vue";
import process from "./process.vue";
import subProcess from "./subProcess.vue";
import wfSubProcess from "./wfSubProcess.vue";
import end from "./end.vue";

import { NodeTypeEnum } from "../enums";

const NODE_NAME_LIST = [
  "custom",
  "decision",
  "end",
  "fork",
  "join",
  "start",
  "task",
  "transition",
  "subProcess",
  "wfSubProcess",
] as string[];

const state = reactive({
  ruleForm: {} as FlowFormModel,
  drawer: {
    isShowDrawer: false,
    title: "",
  },
  component_list: {
    start,
    task,
    decision,
    fork,
    join,
    custom,
    process,
    subProcess,
    wfSubProcess,
    end,
    transition,
  },
  component: null,
});

/**
 * 动态获取组件
 */
const getComponent = (componentName) => {
  return state.component_list[componentName] ?? null;
};

//截取
const extractSubstring = (str) => {
  const index = str.indexOf(":");
  if (index !== -1) {
    return str.substring(index + 1);
  } else {
    return str;
  }
};

// 事件
const emits = defineEmits(["change"]);

// 属性
const props = defineProps({
  extendAttrConfig: {
    // 扩展属性配置
    type: Object,
  },
});

// 节点名称
const nodeName = computed(
  (): NodeTypeEnum => {
    const mFormData = unref(state.ruleForm);
    if (!mFormData || !mFormData.type) return NodeTypeEnum.ignore;
    return (mFormData.type.replace("ingenious:", "") as unknown) as NodeTypeEnum;
  }
);

// 处理emits
const handleEmits = (propertyName: string, propertyValue: any) => {
  if (propertyValue === undefined) return;
  emits("change", {
    type: unref(nodeName),
    propertyName: propertyName,
    propertyValue: propertyValue,
  } as PropertyEvent);
};
// 表单属性keys
const propertyKeys = [
  // 基础属性
  "stroke",
  "fill",
  // 流程属性
  "name",
  "display_name",
  "expire_time",
  "instance_url",
  "instance_no_class",
  // 开始节点和结束节点属性
  "name",
  "pre_interceptors",
  "post_interceptors",
  // 自定义节点属性
  "name",
  "display_name",
  "clazz",
  "method_name",
  "args",
  "pre_interceptors",
  "post_interceptors",
  // 决策节点属性
  "name",
  "expr",
  "handle_class",
  "pre_iterceptors",
  "post_interceptors",
  // 任务节点属性
  "form",
  "assignee",
  "assignment_handler",
  "task_type",
  "perform_type",
  "reminder_time",
  "reminder_repeat",
  "expire_time",
  "auto_execute",
  "callback",
  "width",
  "height",
  "check_model",
  "scope",
  "unattended",
  "automatic",
  "permission",
  "reception",
  "field",
] as string[];

// 去重后的key
const propertyKeysSet = Array.from(new Set(propertyKeys));

//构建监听
propertyKeysSet.forEach((key: string) => {
  //@ts-ignore监听属性变化
  watch(
    () => state.ruleForm[key],
    (n) => handleEmits(key, n),
    { deep: true }
  );
});

// 显示抽屉
const show = (args: FlowFormModel) => {
  // 将args的值复制给formData
  const width = args.width
    ? args.width
    : args.type === "wokingflower:subProcess"
    ? 500
    : 120;
  const height = args.height
    ? args.height
    : args.type === "wokingflower:subProcess"
    ? 300
    : 40;
  Object.assign(state.ruleForm, args, { width: Number(width), height: Number(height) });
  state.drawer.isShowDrawer = true;
  state.component = extractSubstring(args.type);
};

// 抽屉关闭处理
const handleClose = () => {
  state.drawer.isShowDrawer = false;
  // 清空表单值
  Object.keys(state.ruleForm).forEach((key: string) => {
    delete state.ruleForm[key];
  });
  state.component = null; // 销毁动态组件避免再次打开数据污染
};

// 导入属性及方法给外部调用
defineExpose({
  show,
  handleClose,
});
</script>

<style>
.fieldset {
  position: relative;
  border: 1px dashed #ccc;
  border-radius: 2px;
  padding: 10px;
  margin-bottom: 20px;
  background-color: #fff; /* 背景色与文字颜色相同 */
  margin-top: 20px; /* 添加顶部空间 */
}

.legend {
  position: absolute;
  top: -10px;
  left: 10px;
  background-color: #fff; /* 背景色与虚线边框颜色相同 */
  color: #1688f1;
  padding: 0 10px;
  font-weight: bold;
}
</style>
